package com.frozenlab.android.weather.activity;

import java.util.Random;

import com.frozenlab.android.weather.adapter.WeatherAdapter;
import com.frozenlab.android.weather.helper.AudioHelper;
import com.frozenlab.android.weather.helper.WundergroundWeatherHelpher;
import com.frozenlab.android.weather.listener.ShakeEventListener;
import com.frozenlab.android.weather.vo.ForecastVO;
import com.frozenlab.android.weather.vo.LocationVO;
import com.frozenlab.android.weather.vo.WeatherVO;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class SecQWeatherActivity extends Activity implements LocationListener {
	
	private static final String TAG = "SecQWeatherActivity";
	
	private Resources res;
	private static final int MENU_PREFERENCES = 0;
	
	/* Symbol */
	private String DEGREE_SYMBOL;
	
	private View vMain;
	
	private TextView tvLocation;
	private TextView tvCondition;
	private TextView tvTemperature;
	private TextView tvDateLastUpdated;
	
	private TextView tvForecastDay1;
	private TextView tvForecastDay2;
	private TextView tvForecastDay3;
	
	private TextView tvForecastHigh1;
	private TextView tvForecastHigh2;
	private TextView tvForecastHigh3;
	
	private TextView tvForecastLow1;
	private TextView tvForecastLow2;
	private TextView tvForecastLow3;
	
	private ImageView ivWeather;
	private ImageView ivWeatherForecast1;
	private ImageView ivWeatherForecast2;
	private ImageView ivWeatherForecast3;
	
	private LocationManager locationManager;
	private String provider;
	private Location location;
	private LocationVO locationVO = new LocationVO();
	private WeatherVO weatherVO = new WeatherVO();
	
	private SharedPreferences sharedPreferences;
	private SensorManager mSensorManager;
	private ShakeEventListener mSensorListener;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ProgressDialog dialog = ProgressDialog.show(this, "", "Loading. Please wait...", true);
        
        setContentView(R.layout.main);
        
        res = getResources();
        DEGREE_SYMBOL = res.getString(R.string.SymbolDegree);

        vMain = findViewById(R.id.linearLayoutMain);
        
        tvLocation = (TextView) findViewById(R.id.Location);
        tvCondition = (TextView) findViewById (R.id.Condition);
        tvTemperature = (TextView) findViewById (R.id.Temperature);
        tvDateLastUpdated = (TextView) findViewById(R.id.DateLastUpdate);
        
        tvForecastDay1 = (TextView) findViewById (R.id.ForecastDay1);
        tvForecastDay2 = (TextView) findViewById (R.id.ForecastDay2);
        tvForecastDay3 = (TextView) findViewById (R.id.ForecastDay3);
        
        tvForecastHigh1 = (TextView) findViewById (R.id.ForecastHigh1);
        tvForecastHigh2 = (TextView) findViewById (R.id.ForecastHigh2);
        tvForecastHigh3 = (TextView) findViewById (R.id.ForecastHigh3);
        
        tvForecastLow1 = (TextView) findViewById (R.id.ForecastLow1);
        tvForecastLow2 = (TextView) findViewById (R.id.ForecastLow2);
        tvForecastLow3 = (TextView) findViewById (R.id.ForecastLow3);
        
        ivWeather = (ImageView) findViewById(R.id.imageWeather);
        ivWeatherForecast1 = (ImageView) findViewById(R.id.imageWeatherForecast1);
        ivWeatherForecast2 = (ImageView) findViewById(R.id.imageWeatherForecast2);
        ivWeatherForecast3 = (ImageView) findViewById(R.id.imageWeatherForecast3);

        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        
        mSensorListener = new ShakeEventListener();
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mSensorManager.registerListener(mSensorListener,
        mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_UI);

        initCurrentWeather();
        dialog.dismiss();
        
		mSensorListener.setOnShakeListener(new ShakeEventListener.OnShakeListener() {
			public synchronized void onShake() {
				playSound();
			}
		});
    }

	private void initCurrentWeather() {
		locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		
		Criteria criteria = new Criteria();
		provider = locationManager.getBestProvider(criteria, false);
		location = locationManager.getLastKnownLocation(provider);
		
		if(location == null){
			Log.e(TAG,"Location is NULL");
			tvLocation.setText("Detecting location...");
		}
		
		/* request the weather only if the location is not null and network is available */
		if(location != null && isNetworkAvailable()){			
			updateCurrentWeather();
		}else{
			Log.e(TAG,"Network error");
			Toast.makeText(this, "Network error, Please check setting.", Toast.LENGTH_SHORT).show();	
		}
				
	}
	
	private void updateCurrentWeather() {
		Log.e(TAG, "Provider " + provider + " has been selected.");
		double latitude = location.getLatitude();
		double longitude = location.getLongitude();
		Log.e(TAG, "Latitude ="+latitude +" Longtitude="+longitude);
		
		locationVO.setLatitude(String.valueOf(latitude));
		locationVO.setLongitude(String.valueOf(longitude));
		
		//set to SharePreferences for widget usage @can move to preferences file in future
        SharedPreferences preferences = this.getSharedPreferences("weather_preferences", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString("latitude", locationVO.getLatitude());
        editor.putString("longitude", locationVO.getLongitude());
        editor.commit();
		
		/* get the location details using latitude and longitude */
		//LocationAdapter locationAdapter = new LocationAdapter();
		//locationVO = locationAdapter.getLocationByCoordinate(locationVO, locationVO.getLatitude(), locationVO.getLongitude());
		
		/* get weather info */
		WeatherAdapter weatherAdapter = new WeatherAdapter();
		weatherVO = weatherAdapter.getWeatherByCoordinate(locationVO.getLatitude(), locationVO.getLongitude());
		
		/* populate details to screen */
		ForecastVO[] forecastVOArray = weatherVO.getForecastVOArray();
			
		tvLocation.setText(weatherVO.getCity());
		tvCondition.setText(weatherVO.getConditionText());
		tvDateLastUpdated.setText(weatherVO.getConditionDate());
		tvTemperature.setText(showTemperature(weatherVO.getConditionTemperature()));
		

		if(weatherVO.getConditionCode() != null){
			ivWeather.setImageResource(getWeatherImageByCode(weatherVO.getConditionCode()));
			vMain.setBackgroundResource(getWeatherBackgroundByCode(weatherVO.getConditionCode()));
		}
		
		//tvHigh.setText(res.getString(R.string.H) + forecastVOArray[0].getForecastHigh() + res.getString(R.string.SymbolDegree));
		//tvLow.setText(res.getString(R.string.L) + forecastVOArray[0].getForecastLow() + res.getString(R.string.SymbolDegree));
		
		/* populate forecast details */
		ivWeatherForecast1.setImageResource(getWeatherImageByCode(forecastVOArray[1].getForecastCode()));
		ivWeatherForecast2.setImageResource(getWeatherImageByCode(forecastVOArray[2].getForecastCode()));
		ivWeatherForecast3.setImageResource(getWeatherImageByCode(forecastVOArray[3].getForecastCode()));
		
		tvForecastDay1.setText(forecastVOArray[1].getForecastDay());
		tvForecastDay2.setText(forecastVOArray[2].getForecastDay());
		tvForecastDay3.setText(forecastVOArray[3].getForecastDay());
		
		tvForecastHigh1.setText(res.getString(R.string.H) + showTemperature(forecastVOArray[1].getForecastHigh()));
		tvForecastHigh2.setText(res.getString(R.string.H) + showTemperature(forecastVOArray[2].getForecastHigh()));
		tvForecastHigh3.setText(res.getString(R.string.H) + showTemperature(forecastVOArray[3].getForecastHigh()));
		
		tvForecastLow1.setText(res.getString(R.string.L) + showTemperature(forecastVOArray[1].getForecastLow()));
		tvForecastLow2.setText(res.getString(R.string.L) + showTemperature(forecastVOArray[2].getForecastLow()));
		tvForecastLow3.setText(res.getString(R.string.L) + showTemperature(forecastVOArray[3].getForecastLow()));

		
	}

	@Override
	protected void onResume() {
		super.onResume();
		locationManager.requestLocationUpdates(provider, 400, 1, this);
		
	    mSensorManager.registerListener(mSensorListener,
		        mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
		        SensorManager.SENSOR_DELAY_UI);
	}
	
	/* to check is network available. this part can move to component in future */
	private boolean isNetworkAvailable() {
	    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
	    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
	    return activeNetworkInfo != null;
	}

	@Override
	public void onLocationChanged(Location location) {
		//temporary disable this because wunderground.com only able 500 calls per day
		//updateCurrentWeather();
		
	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onProviderEnabled(String provider) {
		Toast.makeText(this, "Enabled new provider " + provider, Toast.LENGTH_SHORT).show();

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		Toast.makeText(this, "Disabled provider " + provider, Toast.LENGTH_SHORT).show();
		
	}
	
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(Menu.NONE, 0, 0, "Preferences");
        menu.add(Menu.NONE, 1, 1, "Refresh");
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case 0:
                this.startActivityForResult(new Intent(this, SecQWeatherPreferenceActivity.class), MENU_PREFERENCES);
                return true;
            case 1:
                this.updateCurrentWeather();
                return true;
        }
        return false;
    }
    
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		switch(requestCode)
		{
			case MENU_PREFERENCES:
				updateCurrentWeather();
		}
	}
	
	@Override
	protected void onStop() {
		mSensorManager.unregisterListener(mSensorListener);
		super.onStop();
	}

	private int getWeatherImageByCode(String strCode){
    	int imageCode = R.drawable.unknown;
    	
    	if (strCode == null){
    		Log.e(TAG,"Code is null");
    		return imageCode;
    	}
    	
    	return WundergroundWeatherHelpher.weatherImageMap.get(strCode);
    }
	
	private int getWeatherBackgroundByCode(String strCode){
    	int imageCode = R.drawable.background_unknown;
    	
    	if (strCode == null){
    		Log.e(TAG,"Code is null");
    		return imageCode;
    	}
    	
    	return WundergroundWeatherHelpher.weatherBackgroundMap.get(strCode);
    }

    private String showTemperature(String temperature){
    	String temperatureUnit = sharedPreferences.getString("temperatureUnit", "F");
    	
    	if (temperatureUnit.equalsIgnoreCase("F")) {
    		temperature = temperature + DEGREE_SYMBOL + temperatureUnit;
    	}else{
    		temperature = WundergroundWeatherHelpher.convertFahrenheitToCelcius(temperature);
    		temperature = temperature + DEGREE_SYMBOL + temperatureUnit;
    	}
    	return temperature;
    }
    
    private void playSound(){
    	//stop shake listener
		mSensorManager.unregisterListener(mSensorListener);
		
    	Random random = new Random();
    	int randomInt = random.nextInt(7); //random 0-6
    	
    	MediaPlayer mediaPlayer = MediaPlayer.create(this, AudioHelper.audioRawMap.get(randomInt));
    	
    	Toast.makeText(SecQWeatherActivity.this, AudioHelper.audioStringMap.get(randomInt), Toast.LENGTH_SHORT).show();
    	mediaPlayer.start(); 
    	mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
			@Override
			public void onCompletion(MediaPlayer mp) {
				//resume shake listener after media end
			    mSensorManager.registerListener(mSensorListener,
				        mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				        SensorManager.SENSOR_DELAY_UI);
			}
		});
    }
}